using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Reflection;
using System.Text;

using Kenly.DBFramework.Gateway;

namespace Kenly.DBFramework.Reflection
{
    /// <summary>
    /// 
    /// </summary>
    public static class EntityUtility
    {
        /// <summary>
        ///  Copies the property values from source to target.
        /// </summary>
        /// <param name="targetEntities"></param>
        /// <param name="sourceEntities"></param>
        public static void ShadowCopy(IList targetEntities, IList sourceEntities)
        {
            if (targetEntities == null || sourceEntities == null || targetEntities.Count != sourceEntities.Count)
            {
                return;
            }

            int i = 0;
            foreach (object srcEntity in sourceEntities)
            {
                ShadowCopy(targetEntities[i], srcEntity);
                i++;
            }
        }

        /// <summary>
        ///  Copies the property values from source to target.
        /// </summary>
        /// <param name="targetEntity"></param>
        /// <param name="sourceEntity"></param>
        public static void ShadowCopy(object targetEntity, object sourceEntity)
        {
            if (targetEntity == null || sourceEntity == null)
            {
                return;
            }
            Type objectType = targetEntity.GetType();
            Type sourceType = sourceEntity.GetType();

            object value = new object();

            Dictionary<string, PropertyInfo> sourceProperties = GetProperties(sourceType);

            foreach (System.Reflection.PropertyInfo objPropertyInfo in objectType.GetProperties())
            {
                if (!objPropertyInfo.CanWrite)
                {
                    continue;
                }

                if (sourceProperties.ContainsKey(objPropertyInfo.Name))
                {
                    value = sourceProperties[objPropertyInfo.Name].GetValue(sourceEntity, null);
                    objPropertyInfo.SetValue(targetEntity, value, null);
                }

            }

        }

        private static Dictionary<string, PropertyInfo> GetProperties(Type type)
        {
            Dictionary<string, PropertyInfo> properties = new Dictionary<string, PropertyInfo>();
            if (type == null)
            {
                return properties;
            }

            foreach (PropertyInfo propertyInfo in type.GetProperties())
            {
                if (!properties.ContainsKey(propertyInfo.Name))
                {
                    properties.Add(propertyInfo.Name, propertyInfo);
                }
            }

            return properties;
        }



        /// <summary>
        /// Inherits the column property values from source entities.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entities"></param>
        /// <returns></returns>
        public static List<T> Inherit<T>(IList entities)
        {
            if (entities == null || entities.Count <= 0)
            {
                return new List<T>();
            }
            List<T> newTargetObjects = ObjectBuilder.CreateInstances<T>(entities.Count);

            ShadowCopy(newTargetObjects, entities);

            return newTargetObjects;
        }

        /// <summary>
        /// Inherits the column property values from source entity.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <returns></returns>
        public static T Inherit<T>(object entity)
        {
            T newTargetObject = ObjectBuilder.CreateInstance<T>();
            ShadowCopy(newTargetObject, entity);
            return newTargetObject;
        }

        /// <summary>
        ///  Inherits the column property values from source entities.
        /// </summary>
        /// <typeparam name="TInput"></typeparam>
        /// <typeparam name="TOutput"></typeparam>
        /// <param name="baseEntities"></param>
        /// <param name="converter"></param>
        /// <returns></returns>
        public static List<TOutput> Inherit<TInput, TOutput>(IList<TInput> baseEntities, Converter<TInput, TOutput> converter)
        {
            List<TOutput> newTargetObjects = ObjectBuilder.CreateInstances<TOutput>(baseEntities.Count);
            int i = 0;
            foreach (TInput entity in baseEntities)
            {
                newTargetObjects[i] = converter(entity);
                i++;
            }
            return newTargetObjects;
        }

        /// <summary>
        /// Inherits the column property values from source entity.
        /// </summary>
        /// <typeparam name="TInput"></typeparam>
        /// <typeparam name="TOutput"></typeparam>
        /// <param name="baseEntity"></param>
        /// <param name="converter"></param>
        /// <returns></returns>
        public static TOutput Inherit<TInput, TOutput>(TInput baseEntity, Converter<TInput, TOutput> converter)
        {
            return converter(baseEntity);
        }

    }
}
